<?php
/**
 *      DropboxClient
 *      Dropbox PHP Api Client
 *      version: 0.5
 *
 *      Author: Szikszai Gusztáv
 *      Copyright: Szikszai Gusztáv 2010
 *      License: MIT
 *      
 *      Requries oauth php extension  
 *
 *      Shared parameters $path,$from_path,$to_path
 *          The path of the file/directory relative to the root (sandbox or dropbox)
 **/
class DropboxClient{
    //the Dropbox Api version
    private $version="0";
    //Host url
    private $host="http://api.dropbox.com/";
    //Host content url for files
    private $hostContent="http://api-content.dropbox.com/";
    // autherizeon url
    private $authorize="/oauth/authorize";
    // request_token url
    private $requestToken="/oauth/request_token";
    // access_token url
    private $accessToken="/oauth/access_token";
    //OAuth object
    private $oauth;
    //root can be sandbox or dropbox
    private $root="sandbox";
    /**
     *  Constructor
     *  @param $consumer_token
     *      Consumer token
     *  @param $consumer_secret
     *      Consumer secret
     **/
    public function __construct($consumer_token,$consumer_secret){
        $this->ctoken=$consumer_token;
        $this->csecret=$consumer_secret;
        $this->oauth = new OAuth($consumer_token,$consumer_secret,OAUTH_SIG_METHOD_HMACSHA1);
    }
    /**
     *  fetch
     *
     *  Handles oauth fetches
     *  @private
     *  
     * */
    private function fetch($url,$params=array(),$headers=array(),$method=OAUTH_HTTP_METHOD_GET){
        try{
            if(preg_match('/^\/files/',$url)==1 || preg_match('/^\/thumbnails/',$url)==1)
                $uri=$this->hostContent.$this->version.$url;
            else
                $uri=$this->host.$this->version.$url;
            $this->oauth->fetch($uri,$params,$method,$headers);
            return $this->oauth->getLastResponse();
        }catch(OAuthException $E) {
            return $E->getCode();
        }
    }
    /**
     *  setRoot
     *
     *  Set the root for later operations
     *
     *  @param $root
     *      Can be "sandbox" or "dropbox"
     *      
     **/
    public function setRoot($root="sandbox"){
        if($root=='dropbox'){
            $this->root="dropbox";
        }else{
            $this->root="sandbox";
        }
    }
    /**
     *  preparePath,preparePathDirectory
     *
     *  Prepares the path (more like check and correct to be valid)
     *  @private
     * */
    private function preparePath($path){
        if(preg_match("/^\//",$path)==0)
            $path="/".$path;
        return $path;
    }
    private function preparePathDirectory($path){
        if(preg_match("/\/$/",$path)==0)
            $path.="/";
        return $path;
    }
    /**
     *  authorize
     *
     *  Gets a request token and redirects the user to the Service Provider (Dropbox in this case)
     *  @param $callback_url
     *     The callback url to process the given token
     *  @param $params
     *      Additional parameters that will be forwarded to $callback_url
     **/
    public function authorize($callback_url=""){
        try{
            //get Request Token
            $this->oauth->getRequestToken($this->host.$this->version.$this->requestToken);
            $data=$this->oauth->getLastResponse();
            //get the oauth_token and oauth_token_secret from encoded response
            $a=explode('&',$data);
            $b=explode("=",$a[1]);
            $c=explode("=",$a[0]);
            //redirect to dropbox for authentication
            header('Location:'.$this->host.$this->version.$this->authorize.'?oauth_token='.$b[1].'&oauth_callback='.$callback_url);
        }catch(OAuthException $E) {
            die("Response: ". $E->lastResponse);
        }
    }
    /**
     *  accessToken
     *
     *  Gets the access token and secret from the given token
     *  @param $token
     *     The authenticted token
     **/
    public function accessToken($token){
        try{
            //get access token from dropbox with the token thats been sent
            $this->oauth->setToken($token,"");
            $this->oauth->getAccessToken($this->host.$this->version.$this->accessToken);
            $data=$this->oauth->getLastResponse();
            //get the oauth_token and oauth_token_secret from encoded response
            $a=explode('&',$data);
            $b=explode("=",$a[1]);
            $c=explode("=",$a[0]);
            //return an associative array with oauth_token_secret and oauth_token
            return array("secret"=>$c[1],"token"=>$b[1]);
        }catch(OAuthException $E) {
            print_r($E);
            echo "Response: ". $E->lastResponse . "\n";
        }
    }
    /**
     *  setTokenSecret
     *
     *  sets the access token and secret
     *  @param $token
     *     The access token
     *  @param $secret
     *     The access secret
     **/
    public function setToken($token,$secret){
        $this->secret=$secret;
        $this->token=$token;
        $this->oauth->setToken($token,$secret);
    }
    /**
     *  metadata
     *
     *  Retrieve file and folder metadata
     *   
     *  @param $path
     *  @param $list
     *      To list or not the contents of the directory.
     *  @param $limit
     *     See dropbox API documentation
     *
     **/
    public function metadata($path="/",$list='false',$limit=10000){
        $extra=array("list"=>$list);
        return $this->fetch("/metadata/".$this->root.$this->preparePath($path),$extra);
    }
    /**
     *  accountInfo
     *
     *  Retrieve information about the user’s account.
     *  
     **/
    public function accountInfo(){
        return $this->fetch("/account/info");
    }
    /**
     *  files
     *
     *  Retrieve or upload file contents relative to the user’s Dropbox root or the application’s sandbox directory within the user’s Dropbox.
     *
     *  @param $path
     *  @param $file
     *  
     **/
    public function files($path,$file=array()){
        $path=$this->preparePath($path);
        if(empty($file)){
            $filename=array_pop(preg_split('/\//',$path));
            $ret=$this->fetch("/files/".$this->root.$path);
        }else{
            $path=$this->preparePathDirectory($path);
            $filename=$file['filename'];

            $mime_boundary=md5(time());
            $headers = array("Content-Type"=>"multipart/form-data; boundary=".$mime_boundary);

            $body = "--".$mime_boundary."\r\n";
            $body .= 'Content-Disposition: form-data; name=file; filename='.$filename."\r\n";
            $body .= "Content-Type: ".$file['content-type']."\r\n\r\n";
            $body .=$file['content']."\r\n";
            $body .= "--".$mime_boundary."--";
            
            $path.="files/".$this->root.$path."?file=".oauth_urlencode($filename);
            $ret=$this->fetch($path,$body,$headers,OAUTH_HTTP_METHOD_POST);
        }
        return $ret;
    }
    /**
     *   links
     *
     *   Redirect the user to a cookie-protected URL for viewing the file
     *   
     *   @param $path
     *
     **/
    public function links($path){
      header('Location:'.$this->host.$this->version.$url."/links/".$this->root.$this->preparePath($path));
    }
    /**
     *  files
     *
     *  Files and folders can be moved, copied, or deleted, and folders can be created.
     *
     *  @param $operation
     *  @param $from_path
     *  @param $to_path
     * */
    public function fileops($operation,$from_path="/",$to_path="*"){
        $extra=array();
        if($to_path=="*"){
            $extra["path"]=$this->preparePath($from_path);
        }else{
            $extra["from_path"]=$this->preparePath($from_path);
            $extra[ "to_path"]=$this->preparePath($to_path);
        }
        $extra["root"]=$this->root;
        return $this->fetch("/fileops/".$operation,$extra);
    }
    /**
     *  thumbnails
     *
     *  Get a minimized thumbnail in three sizes ‘small’, ‘medium’, and ‘large’ for a photo on mobile. If you want slightly bigger more “desktop friendly” thumbnail sizes then use ‘s’, ‘m’, or ‘l’ alternatives.
     *
     *  @param $path
     *  @param $size
     *      The size of the thumbnail
     *      Can be s,m,l,small,medium,large
     *  
     * */
    public function thumbnails($path,$size){
        if(preg_match('/^[s|l|n]$/',$size)==1 || preg_match('/^small|medium|large$/',$size)==1){
            $extra=array("size"=>$size);
            return $this->fetch("/thumbnails/".$this->root.$this->preparePath($path),$extra);
        }
    }
}

?>